package vn.mahjonggame.game.event;


import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import vn.mahjonggame.game.Mahjong;
import vn.mahjonggame.game.MahjongExtension;
import vn.mahjonggame.game.request.CallRonHandler;
import vn.mahjonggame.game.request.ThrowTileHandler;
import vn.mahjonggame.game.request.UpdateRoomHandler;
import vn.mahjonggame.metadata.GameActionType;
import vn.mahjonggame.metadata.MObject;
import vn.mahjonggame.metadata.MatchState;
import vn.mahjonggame.metadata.Player;
import vn.mahjonggame.metadata.PlayerMode;
import vn.mahjonggame.metadata.Response;
import vn.mahjonggame.metadata.RoomVarName;
import vn.mahjonggame.metadata.UserVarName;
import vn.mahjonggame.platform.PlatformClient;
import vn.mahjonggame.util.Common;

import com.smartfoxserver.v2.core.ISFSEvent;
import com.smartfoxserver.v2.core.SFSEventParam;
import com.smartfoxserver.v2.core.SFSEventType;
import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSArray;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.entities.variables.RoomVariable;
import com.smartfoxserver.v2.entities.variables.SFSRoomVariable;
import com.smartfoxserver.v2.exceptions.SFSException;
import com.smartfoxserver.v2.extensions.BaseServerEventHandler;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;

public class OnUserGoneHandler extends BaseServerEventHandler {
		
	@Override
	public void handleServerEvent(ISFSEvent event) throws SFSException {
		// TODO Auto-generated method stub
		User user = (User) event.getParameter(SFSEventParam.USER);		
		MahjongExtension ext = (MahjongExtension) getParentExtension();		
		
		Mahjong mahjong = ext.getMahjong();
		List<Player> players = mahjong.getPlayers();
		Room room = ext.getGameRoom();
		Logger logger = mahjong.getLogger();
		int roomBet = room.getVariable(RoomVarName.roomBet.toString()).getIntValue();
		
		List<User> users = room.getUserList();
		
		Player player = mahjong.getPlayerById(user.getId());
		player.cancelTimer();
		
		Player nextPlayer = mahjong.getNextPlayer(player);
				
		logger.info(mahjong.log(room, player, GameActionType.leave.toString(), "matchState: " + ext.getMatchState()));		
		if(ext.getMatchState() != MatchState.PLAYING && ext.getMatchState() != MatchState.SHOW_RESULT) {
			
			if (ext.getPlayerMode() == PlayerMode.REAL_MODE.ordinal()){
				SFSObject response = mahjong.gamePlayerLeave(user, GameActionType.leave.toString());
				if(response != null){
					send(GameActionType.leave.toString(), response, user);
					return;
				}
			}
			
			User ownerO = room.getOwner();			
			
			if(user.getId() == ownerO.getId()){
				send(GameActionType.outRoom.toString(), new SFSObject(), users);
				ext.removeRoom();
				logger.info(mahjong.log(room, player, GameActionType.leave.toString(), "Send outRoom cmd"));				
			}
			else {
				UpdateRoomHandler updateRoomHandler = new UpdateRoomHandler();
				updateRoomHandler.updateRoom(ext, user, false);											
				logger.info(mahjong.log(room, player, GameActionType.leave.toString(), "Send updateRoom cmd"));							
			}
			
			ext.getPlayers().remove(user);
			mahjong.getPlayers().remove(player);
			ext.getEmptyPosition().add(player.getPlayerPosition());
			logger.info(mahjong.log(room, player, GameActionType.leave.toString(), "Available Position: " + ext.getEmptyPosition()));
		}
		else {
			room.addUser(user);
			player.setDisconnect(true);
			logger.info(mahjong.log(room, player, GameActionType.leave.toString(), "Dont remove, just set the player status to DISCONNECT"));
			
			if(player.equals(mahjong.getPlayerInTurn()) 
					&& !mahjong.canRon() 
					&& ext.getMatchState() == MatchState.PLAYING){
				logger.info(mahjong.log(room, player, GameActionType.leave.toString(), "Calling throw handler..."));
				ThrowTileHandler throwTileHandler = new ThrowTileHandler();
				Response.Builder params = new Response.Builder();
				params.tile(player.getJustPickedTile().getId())
						.bonusTime(0);						
				throwTileHandler.throwTile(ext, user, params.build().getSFSObject(), false, false);
			}
		}
				
		/*
		 * Call RON if only 1 player in Room
		 */
		if (mahjong.canRon() && ext.getMatchState() != MatchState.SHOW_RESULT){
			logger.info(mahjong.log(room, player, GameActionType.leave.toString(), "Only 1 player is in Mahjong"));
			mahjong.getPlayerInTurn().cancelTimer();
			/*
			 * Build the amount of each player to send to API server
			 */
			SFSArray userAmounts = new SFSArray();
			for(int i = 0; i < users.size(); i++){
				User iUser = users.get(i);
				
				Response.Builder userAmount = new Response.Builder();
				Player iPlayer = mahjong.getPlayerById(iUser.getId());				
				userAmount.user_id(iUser.getName());
				
				if(iPlayer.isDisconnect()){
					userAmount.amount(-roomBet);					
				}
				else {
					userAmount.amount(3 * roomBet);					
				}				
				
				userAmounts.addSFSObject(userAmount.build().getSFSObject());
			}
			/*
			 * Call game_finish_game API
			 */
			if (ext.getPlayerMode() == PlayerMode.REAL_MODE.ordinal()){				
				SFSObject response = mahjong.gameFinishGame(player, GameActionType.leave.toString());
				if(response != null){
					send(GameActionType.leave.toString(), response, users);
					return;
				}							
			}
			
			SFSArray sfsPlayerArray = new SFSArray();			
			Response.Builder object = new Response.Builder();
			object.winPos(nextPlayer.getPlayerPosition())
					.losePos(player.getPlayerPosition())
					.loseTile(-1)
					.winTile(-1);			
			
			for(int i = 0; i < players.size(); i++){
				
				Player iPlayer = players.get(i);
				User iUser = mahjong.getUserByPlayerId(iPlayer.getPlayerId(), users);
				
				Response.Builder sfsUser = new Response.Builder();
				
				if(ext.getPlayerMode() == PlayerMode.REAL_MODE.ordinal() && iUser != null){
					
					SFSObject response = mahjong.useGetBalance(sfsUser, iUser, iPlayer, GameActionType.leave.toString());
					if(response != null){
						send(GameActionType.leave.toString(), response, users);
						return;
					}									
				}
				else{
					if(iPlayer.isDisconnect()){
						sfsUser.money(-roomBet);						
					}
					else {
						sfsUser.money(3 * roomBet);						
					}					
				}
								
				if(iPlayer.isDisconnect()){
					sfsUser.isWinner(false);					
				}
				else {
					sfsUser.isWinner(true);					
				}
				
				sfsUser.name(iPlayer.getName())
						.tiles(mahjong.tileArrayToTileIdArray(iPlayer.getLeftTiles()));
				
				logger.info(mahjong.log(room, player, GameActionType.leave.toString(), "Player " + iPlayer.toString() + " " + iPlayer.getLeftTiles()));
				sfsPlayerArray.addSFSObject(sfsUser.build().getSFSObject());
			}
						
			Response.Builder response = new Response.Builder();
			response.RON(object.build().getSFSObject())
					.turn(nextPlayer.getPlayerPosition())
					.players(sfsPlayerArray);
			
			logger.info(mahjong.log(room, player, GameActionType.leave.toString(), "Send callRon cmd"));
			send(GameActionType.callRon.toString(), response.build().getSFSObject(), users);
		}
		else if(room.getUserList().size() == 0 || mahjong.canBeRemove()){
			ext.removeRoom();
			logger.info(mahjong.log(room, player, GameActionType.leave.toString(), "Removed room " + room.getName() + "-" + room.getId()));
		}
				
		/*
		 * Update the number of players on GUI
		 */		
		users = room.getUserList();
		SFSArray sfsUserArray = new SFSArray();
		
		for(int i = 0; i < users.size(); i++){
			User iUser = users.get(i);
			SFSObject oUser = new SFSObject();
			oUser.putUtfString(UserVarName.name.toString(), iUser.getName());
			oUser.putUtfString(UserVarName.avatar.toString(), iUser.getVariable(UserVarName.avatar.toString()).getStringValue());
			
			sfsUserArray.addSFSObject(oUser);
		}
		
		RoomVariable usersVar = new SFSRoomVariable(MObject.users.toString(), sfsUserArray);
		usersVar.setOwner(null);			
		usersVar.setGlobal(true);       
        getApi().setRoomVariables(null, room, Arrays.asList(usersVar));
        
        /*
		 * User disconnected
		 */
		if (event.getType() == SFSEventType.USER_DISCONNECT)
		{			
			ext.addAction(user, GameActionType.disconnect.toString());
		} 
		else { 			
			ext.addAction(user, GameActionType.leave.toString());
		}			
			
	}

}
